/**
 * libGeoutils 完整示例应用程序
 * 
 * 这个示例展示了如何综合使用 libGeoutils 库的各种功能：
 * 1. 创建和管理地理坐标
 * 2. 计算地理距离和方位角
 * 3. 路径管理和序列化
 * 4. 属性管理
 * 5. UUID 和时间戳
 * 6. 颜色映射
 * 7. 数据归一化
 */

#include "libGeoutils/shape/Coord.h"
#include "libGeoutils/shape/CoordZ.h"
#include "libGeoutils/shape/Polyline.h"
#include "libGeoutils/shape/Rectangle.h"
#include "libGeoutils/shape/Segment.h"
#include "libGeoutils/tool/shape_tool.h"
#include "libGeoutils/tool/datetime_tool.h"
#include "libGeoutils/tool/uuid_tool.h"
#include "libGeoutils/tool/color_mapper.h"
#include "libGeoutils/tool/normalize_tool.h"
#include "libGeoutils/property/properties.h"

#include <iostream>
#include <vector>
#include <memory>
#include <iomanip>

// ============================================================================
// 辅助函数
// ============================================================================

void printSeparator(const std::string& title = "") {
    std::cout << "\n" << std::string(70, '=') << std::endl;
    if (!title.empty()) {
        std::cout << "  " << title << std::endl;
        std::cout << std::string(70, '=') << std::endl;
    }
}

void printCoord(const std::string& name, const geo::shape::Coord& coord) {
    std::cout << std::fixed << std::setprecision(6);
    std::cout << name << ": (" 
              << coord.getLongitude() << ", " 
              << coord.getLatitude() << ")" << std::endl;
}

// ============================================================================
// 示例1: 基础坐标和距离计算
// ============================================================================

void example1_BasicCoordinates() {
    printSeparator("示例 1: 基础坐标和距离计算");
    
    // 创建中国主要城市坐标
    struct City {
        std::string name;
        geo::shape::Coord coord;
    };
    
    std::vector<City> cities = {
        {"北京", geo::shape::Coord(116.4074, 39.9042)},
        {"上海", geo::shape::Coord(121.4737, 31.2304)},
        {"广州", geo::shape::Coord(113.2644, 23.1291)},
        {"深圳", geo::shape::Coord(114.0579, 22.5431)},
        {"成都", geo::shape::Coord(104.0668, 30.5728)},
        {"西安", geo::shape::Coord(108.9398, 34.3416)}
    };
    
    // 创建地理工具
    geo::tool::ShapeTool shape_tool;
    
    // 计算北京到其他城市的距离
    std::cout << "\n从北京到各城市的距离:" << std::endl;
    for (size_t i = 1; i < cities.size(); ++i) {
        double distance, bearing;
        shape_tool.calc_coord_distance(cities[0].coord, cities[i].coord, distance);
        shape_tool.calc_coord_bearing(cities[0].coord, cities[i].coord, bearing);
        
        std::cout << "  " << std::setw(6) << cities[i].name 
                  << ": " << std::setw(8) << std::fixed << std::setprecision(2) 
                  << distance << " km, 方位角: " << std::setw(6) << bearing << "°" << std::endl;
    }
    
    // 计算目标点
    std::cout << "\n从北京出发的目标点计算:" << std::endl;
    std::vector<std::pair<std::string, double>> directions = {
        {"正北", 0.0}, {"东北", 45.0}, {"正东", 90.0}, 
        {"东南", 135.0}, {"正南", 180.0}, {"西南", 225.0},
        {"正西", 270.0}, {"西北", 315.0}
    };
    
    double test_distance = 100.0; // 100公里
    for (const auto& [dir_name, bearing] : directions) {
        auto dest = shape_tool.calc_destination(cities[0].coord, test_distance, bearing);
        std::cout << "  " << std::setw(6) << dir_name << " 100km: (" 
                  << dest.getLongitude() << ", " << dest.getLatitude() << ")" << std::endl;
    }
}

// ============================================================================
// 示例2: 路径管理
// ============================================================================

void example2_RouteManagement() {
    printSeparator("示例 2: 路径管理");
    
    // 创建京沪高铁路线
    geo::shape::Polyline route;
    
    // 添加站点
    std::vector<std::pair<std::string, geo::shape::Coord>> stations = {
        {"北京南", geo::shape::Coord(116.3783, 39.8651)},
        {"天津南", geo::shape::Coord(117.2161, 38.9980)},
        {"济南西", geo::shape::Coord(116.8520, 36.6758)},
        {"南京南", geo::shape::Coord(118.8444, 31.9515)},
        {"苏州北", geo::shape::Coord(120.5636, 31.4105)},
        {"上海虹桥", geo::shape::Coord(121.3202, 31.1945)}
    };
    
    for (const auto& [name, coord] : stations) {
        route.appendCoord(std::make_shared<geo::shape::Coord>(coord));
    }
    
    // 添加路线属性
    route.setProperty<std::string>("route_name", "京沪高铁");
    route.setProperty<std::string>("route_id", geo::tool::UUID_Identifier::CreateUUID());
    route.setProperty<std::string>("type", "high_speed_rail");
    route.setProperty<int>("max_speed", 350);
    route.setProperty<std::string>("created_at", geo::tool::DateTime::now_str());
    
    // 计算总距离
    geo::tool::ShapeTool tool;
    auto coords = route.getCoords();
    double total_distance = 0.0;
    
    std::cout << "\n京沪高铁站点和区间距离:" << std::endl;
    for (size_t i = 0; i < coords.size() - 1; ++i) {
        double segment_dist;
        tool.calc_coord_distance(coords[i], coords[i+1], segment_dist);
        total_distance += segment_dist;
        
        std::cout << "  " << stations[i].first << " -> " << stations[i+1].first 
                  << ": " << segment_dist << " km" << std::endl;
    }
    
    route.setProperty<double>("total_distance", total_distance);
    
    std::cout << "\n路线信息:" << std::endl;
    std::string route_name, route_id, created_at;
    int max_speed;
    route.getProperty("route_name", route_name);
    route.getProperty("route_id", route_id);
    route.getProperty("max_speed", max_speed);
    route.getProperty("created_at", created_at);
    
    std::cout << "  名称: " << route_name << std::endl;
    std::cout << "  ID: " << route_id << std::endl;
    std::cout << "  最高时速: " << max_speed << " km/h" << std::endl;
    std::cout << "  站点数: " << coords.size() << std::endl;
    std::cout << "  总距离: " << total_distance << " km" << std::endl;
    std::cout << "  创建时间: " << created_at << std::endl;
    
    // 保存到文件
    if (route.toJsonFile("beijing_shanghai_railway.json")) {
        std::cout << "\n路线已保存到 beijing_shanghai_railway.json" << std::endl;
    }
    
    // 序列化为 JSON 字符串
    std::string json_str;
    if (route.to_json(json_str)) {
        std::cout << "\nJSON 数据（前200字符）:" << std::endl;
        std::cout << json_str.substr(0, 200) << "..." << std::endl;
    }
}

// ============================================================================
// 示例3: 矩形边界和圆形区域
// ============================================================================

void example3_BoundingBoxAndCircle() {
    printSeparator("示例 3: 矩形边界和圆形区域");
    
    // 创建中国大陆边界框
    geo::shape::Rectangle china_bbox(73.5, 135.0, 18.2, 53.5);
    china_bbox.setProperty<std::string>("region", "中国大陆");
    china_bbox.setProperty<std::string>("country", "中国");
    
    std::cout << "\n中国大陆边界框:" << std::endl;
    std::cout << "  经度范围: [" << china_bbox.getMinLon() 
              << ", " << china_bbox.getMaxLon() << "]" << std::endl;
    std::cout << "  纬度范围: [" << china_bbox.getMinLat() 
              << ", " << china_bbox.getMaxLat() << "]" << std::endl;
    
    // 计算以北京为中心的圆形区域
    geo::tool::ShapeTool tool;
    geo::shape::Coord beijing(116.4074, 39.9042);
    double radius = 50.0; // 50公里半径
    int num_points = 16;
    geo::shape::Rectangle circle_bbox;
    
    std::cout << "\n北京周边50公里圆形区域（16个点）:" << std::endl;
    auto circle_points = tool.calculate_circle_points(
        beijing, radius, 0.0, num_points, circle_bbox
    );
    
    for (size_t i = 0; i < circle_points.size(); ++i) {
        const auto& point = circle_points[i].first;
        double bearing = (360.0 / num_points) * i;
        std::cout << "  方位 " << std::setw(3) << (int)bearing << "°: (" 
                  << point.getLongitude() << ", " 
                  << point.getLatitude() << ")" << std::endl;
    }
    
    std::cout << "\n圆形区域边界框:" << std::endl;
    std::cout << "  经度范围: [" << circle_bbox.getMinLon() 
              << ", " << circle_bbox.getMaxLon() << "]" << std::endl;
    std::cout << "  纬度范围: [" << circle_bbox.getMinLat() 
              << ", " << circle_bbox.getMaxLat() << "]" << std::endl;
}

// ============================================================================
// 示例4: 颜色映射和数据可视化
// ============================================================================

void example4_ColorMapping() {
    printSeparator("示例 4: 颜色映射和数据可视化");
    
    // 创建温度颜色映射器
    geo::tool::ColorMapper temp_mapper("temperature", 1);
    
    // 设置颜色梯度（蓝 -> 青 -> 绿 -> 黄 -> 红）
    temp_mapper.appendColorStop(0.0,  std::make_shared<geo::tool::ColorRGBA>(0, 0, 255, 255));
    temp_mapper.appendColorStop(0.25, std::make_shared<geo::tool::ColorRGBA>(0, 255, 255, 255));
    temp_mapper.appendColorStop(0.5,  std::make_shared<geo::tool::ColorRGBA>(0, 255, 0, 255));
    temp_mapper.appendColorStop(0.75, std::make_shared<geo::tool::ColorRGBA>(255, 255, 0, 255));
    temp_mapper.appendColorStop(1.0,  std::make_shared<geo::tool::ColorRGBA>(255, 0, 0, 255));
    
    // 模拟温度数据（摄氏度）
    std::vector<double> temperatures = {-10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40};
    
    // 归一化温度数据
    geo::tool::Normalizer<double, float> normalizer;
    std::vector<float> normalized_temps;
    normalizer.normalizeVector(temperatures, normalized_temps, 0.0f, 1.0f);
    
    // 映射温度到颜色
    std::cout << "\n温度颜色映射:" << std::endl;
    std::cout << std::setw(8) << "温度(°C)" << " | " 
              << std::setw(10) << "归一化值" << " | " 
              << "RGB颜色" << std::endl;
    std::cout << std::string(50, '-') << std::endl;
    
    for (size_t i = 0; i < temperatures.size(); ++i) {
        auto color = temp_mapper.mapGray2Color(normalized_temps[i]);
        std::cout << std::setw(8) << temperatures[i] << " | " 
                  << std::setw(10) << std::fixed << std::setprecision(3) << normalized_temps[i] << " | "
                  << "RGB(" << std::setw(3) << color->getR() << ", "
                  << std::setw(3) << color->getG() << ", "
                  << std::setw(3) << color->getB() << ")" << std::endl;
    }
    
    // 保存颜色映射器配置
    temp_mapper.toJsonFile("temperature_color_map.json");
    std::cout << "\n颜色映射配置已保存到 temperature_color_map.json" << std::endl;
}

// ============================================================================
// 示例5: 数据归一化
// ============================================================================

void example5_DataNormalization() {
    printSeparator("示例 5: 数据归一化");
    
    // 海拔数据（米）
    std::vector<double> elevations = {-154, 0, 500, 1000, 2000, 3000, 4000, 5000, 8848};
    
    // 创建归一化器
    geo::tool::Normalizer<double, float> normalizer;
    
    // 归一化到 [0, 1]
    std::vector<float> normalized;
    normalizer.normalizeVector(elevations, normalized, 0.0f, 1.0f);
    
    std::cout << "\n海拔数据归一化:" << std::endl;
    std::cout << std::setw(12) << "海拔(米)" << " | " << "归一化值" << std::endl;
    std::cout << std::string(30, '-') << std::endl;
    
    for (size_t i = 0; i < elevations.size(); ++i) {
        std::cout << std::setw(12) << elevations[i] << " | " 
                  << std::fixed << std::setprecision(4) << normalized[i] << std::endl;
    }
    
    // 限制范围
    std::vector<float> limited;
    normalizer.limitVectorMinMax(elevations, limited, 0.0f, 5000.0f);
    
    std::cout << "\n海拔数据限制到 [0, 5000]:" << std::endl;
    std::cout << std::setw(12) << "原始海拔" << " | " << "限制后" << std::endl;
    std::cout << std::string(30, '-') << std::endl;
    
    for (size_t i = 0; i < elevations.size(); ++i) {
        std::cout << std::setw(12) << elevations[i] << " | " 
                  << limited[i] << std::endl;
    }
}

// ============================================================================
// 示例6: 时间戳和UUID
// ============================================================================

void example6_TimestampAndUUID() {
    printSeparator("示例 6: 时间戳和 UUID");
    
    // 创建时间对象
    geo::tool::DateTime event_time(2024, 10, 24, 15, 30, 45);
    
    std::cout << "\n特定时间:" << std::endl;
    std::cout << "  年: " << event_time.getYear() << std::endl;
    std::cout << "  月: " << event_time.getMonth() << std::endl;
    std::cout << "  日: " << event_time.getDay() << std::endl;
    std::cout << "  时: " << event_time.getHour() << std::endl;
    std::cout << "  分: " << event_time.getMinute() << std::endl;
    std::cout << "  秒: " << event_time.getSeconds() << std::endl;
    std::cout << "  字符串: " << event_time.toString() << std::endl;
    
    // 当前时间
    std::cout << "\n当前时间: " << geo::tool::DateTime::now_str() << std::endl;
    
    // 生成 UUID
    std::cout << "\n生成的 UUID:" << std::endl;
    for (int i = 0; i < 5; ++i) {
        std::cout << "  " << (i+1) << ": " 
                  << geo::tool::UUID_Identifier::CreateUUID() << std::endl;
    }
    
    // 为对象添加时间戳和 UUID
    geo::shape::Coord location(116.4074, 39.9042);
    location.setProperty<std::string>("uuid", geo::tool::UUID_Identifier::CreateUUID());
    location.setProperty<std::string>("timestamp", geo::tool::DateTime::now_str());
    location.setProperty<std::string>("location_name", "天安门");
    
    // 保存
    location.toJsonFile("location_with_metadata.json");
    std::cout << "\n带元数据的位置已保存到 location_with_metadata.json" << std::endl;
}

// ============================================================================
// 示例7: 综合应用 - 航线规划系统
// ============================================================================

class FlightRoute {
public:
    FlightRoute(const std::string& flight_no, const std::string& departure, const std::string& arrival)
        : flight_no_(flight_no) {
        
        route_ = std::make_shared<geo::shape::Polyline>();
        route_->setProperty<std::string>("flight_no", flight_no);
        route_->setProperty<std::string>("departure", departure);
        route_->setProperty<std::string>("arrival", arrival);
        route_->setProperty<std::string>("route_id", geo::tool::UUID_Identifier::CreateUUID());
        route_->setProperty<std::string>("plan_time", geo::tool::DateTime::now_str());
    }
    
    void addWaypoint(const std::string& name, double lon, double lat, double altitude = 10000) {
        auto coord = std::make_shared<geo::shape::CoordZ>(lon, lat, altitude);
        route_->appendCoord(coord);
        waypoint_names_.push_back(name);
    }
    
    void calculateRoute() {
        geo::tool::ShapeTool tool;
        auto coords = route_->getCoords();
        
        if (coords.size() < 2) return;
        
        total_distance_ = 0.0;
        segment_distances_.clear();
        
        for (size_t i = 0; i < coords.size() - 1; ++i) {
            double dist;
            if (tool.calc_coord_distance(coords[i], coords[i+1], dist)) {
                segment_distances_.push_back(dist);
                total_distance_ += dist;
            }
        }
        
        route_->setProperty<double>("total_distance_km", total_distance_);
        
        // 估算飞行时间（假设平均速度800 km/h）
        double flight_hours = total_distance_ / 800.0;
        route_->setProperty<double>("estimated_hours", flight_hours);
    }
    
    void printRouteInfo() const {
        std::string flight_no, departure, arrival, route_id;
        route_->getProperty("flight_no", flight_no);
        route_->getProperty("departure", departure);
        route_->getProperty("arrival", arrival);
        route_->getProperty("route_id", route_id);
        
        std::cout << "\n航班信息:" << std::endl;
        std::cout << "  航班号: " << flight_no << std::endl;
        std::cout << "  起飞地: " << departure << std::endl;
        std::cout << "  目的地: " << arrival << std::endl;
        std::cout << "  路线ID: " << route_id << std::endl;
        
        std::cout << "\n航路点:" << std::endl;
        auto coords = route_->getCoords();
        for (size_t i = 0; i < waypoint_names_.size(); ++i) {
            std::cout << "  " << (i+1) << ". " << waypoint_names_[i] 
                      << " (" << coords[i]->getLongitude() << ", " 
                      << coords[i]->getLatitude() << ")";
            
            // 如果是 CoordZ，显示高度
            auto coordz = std::dynamic_pointer_cast<geo::shape::CoordZ>(coords[i]);
            if (coordz) {
                std::cout << " - 高度: " << coordz->getAltitude() << "m";
            }
            std::cout << std::endl;
            
            // 显示区间距离
            if (i < segment_distances_.size()) {
                std::cout << "      ↓ " << segment_distances_[i] << " km" << std::endl;
            }
        }
        
        std::cout << "\n航线统计:" << std::endl;
        std::cout << "  总距离: " << total_distance_ << " km" << std::endl;
        std::cout << "  预计飞行时间: " << (total_distance_ / 800.0) << " 小时" << std::endl;
    }
    
    void saveToFile(const std::string& filename) {
        route_->toJsonFile(filename);
    }
    
private:
    std::string flight_no_;
    std::shared_ptr<geo::shape::Polyline> route_;
    std::vector<std::string> waypoint_names_;
    std::vector<double> segment_distances_;
    double total_distance_ = 0.0;
};

void example7_FlightPlanning() {
    printSeparator("示例 7: 综合应用 - 航线规划系统");
    
    // 创建北京到洛杉矶的航线
    FlightRoute flight("CA983", "北京首都机场", "洛杉矶国际机场");
    
    // 添加航路点
    flight.addWaypoint("北京首都机场", 116.5974, 40.0801, 0);
    flight.addWaypoint("蒙古上空", 106.9, 47.9, 11000);
    flight.addWaypoint("俄罗斯西伯利亚", 100.0, 55.0, 11500);
    flight.addWaypoint("阿拉斯加", -150.0, 65.0, 11000);
    flight.addWaypoint("加拿大上空", -130.0, 55.0, 11200);
    flight.addWaypoint("西雅图上空", -122.3, 47.6, 10000);
    flight.addWaypoint("洛杉矶国际机场", -118.4085, 33.9416, 0);
    
    // 计算航线
    flight.calculateRoute();
    
    // 打印信息
    flight.printRouteInfo();
    
    // 保存
    flight.saveToFile("flight_ca983_route.json");
    std::cout << "\n航线已保存到 flight_ca983_route.json" << std::endl;
}

// ============================================================================
// 主函数
// ============================================================================

int main() {
    std::cout << std::string(70, '=') << std::endl;
    std::cout << "  libGeoutils 完整示例应用程序" << std::endl;
    std::cout << "  展示地理空间数据处理的各种功能" << std::endl;
    std::cout << std::string(70, '=') << std::endl;
    
    try {
        // 运行所有示例
        example1_BasicCoordinates();
        example2_RouteManagement();
        example3_BoundingBoxAndCircle();
        example4_ColorMapping();
        example5_DataNormalization();
        example6_TimestampAndUUID();
        example7_FlightPlanning();
        
        printSeparator();
        std::cout << "\n所有示例运行完成！" << std::endl;
        std::cout << "\n生成的文件:" << std::endl;
        std::cout << "  - beijing_shanghai_railway.json      (京沪高铁路线)" << std::endl;
        std::cout << "  - temperature_color_map.json         (温度颜色映射)" << std::endl;
        std::cout << "  - location_with_metadata.json        (带元数据的位置)" << std::endl;
        std::cout << "  - flight_ca983_route.json            (航班路线)" << std::endl;
        
        printSeparator();
        
    } catch (const std::exception& e) {
        std::cerr << "错误: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}

